/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.farent.solutions.plugins.stripes.hyperstripes.controller;

import com.farent.solutions.plugins.stripes.hyperstripes.core.ajax.AjaxConstants;
import com.farent.solutions.plugins.stripes.hyperstripes.core.ajax.AjaxResponse;
import com.farent.solutions.plugins.stripes.hyperstripes.core.ajax.AjaxResponseWriter;
import com.farent.solutions.plugins.stripes.hyperstripes.core.ComponentAnnotationProcessor;
import com.farent.solutions.plugins.stripes.hyperstripes.core.ComponentModel;
import com.farent.solutions.plugins.stripes.hyperstripes.core.ComponentProcessor;
import com.farent.solutions.plugins.stripes.hyperstripes.core.ComponentTagModelFactory;
import com.farent.solutions.plugins.stripes.hyperstripes.core.ComponentTypeStateHelper;
import com.farent.solutions.plugins.stripes.hyperstripes.core.DefaultComponentTypeStateHelper;
import com.farent.solutions.plugins.stripes.hyperstripes.core.HSActionBean;
import com.farent.solutions.plugins.stripes.hyperstripes.core.HSPageParser;
import com.farent.solutions.plugins.stripes.hyperstripes.core.HyperStripesApplicationContext;
import com.farent.solutions.plugins.stripes.hyperstripes.core.RootComponentModel;
//import com.farent.solutions.ratedInstructor.annotations.Layout;
import com.farent.solutions.plugins.stripes.hyperstripes.core.StripesApplicationContext;
import com.farent.solutions.plugins.stripes.hyperstripes.utils.ServletUtils;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sourceforge.stripes.action.ActionBeanContext;
import net.sourceforge.stripes.action.Resolution;
import org.mvel2.templates.CompiledTemplate;
import org.mvel2.templates.TemplateCompiler;
import org.mvel2.templates.TemplateRuntime;

/**
 *
 * @author user
 */
public abstract class HSPage  implements HSActionBean, Resolution
{
    private StripesApplicationContext hsContext = null;

    private ComponentModel rootModel;

    private boolean redirect;
    
    @Override
    public void execute( HttpServletRequest request,
            HttpServletResponse response ) throws Exception
    {
        //TODO this needs to be done from somewhere..for now here is just about fine
        ServletContext servletContext = request.getSession().getServletContext();
        hsContext = new HyperStripesApplicationContext(servletContext);
        hsContext.init();
        String appURL = ServletUtils.createApplicationUrl(request);
        hsContext.setApplicationUrl(appURL);

        ComponentAnnotationProcessor.getInstance().startUp();
        String pageFile = "pages"+
                File.separator+getClass().getSimpleName() + ".xml";
        InputStream is =  getClass().getResourceAsStream(pageFile);

        if ( rootModel == null ) {
            rootModel = new RootComponentModel();
            DefaultComponentTypeStateHelper stateHelper = new DefaultComponentTypeStateHelper();
            stateHelper.setHsContext(hsContext);
            rootModel.setComponentTypeStateHelper(stateHelper);
            HSPageParser.processTemplateWithReader(is, rootModel, hsContext);
        }

        String partialParam = request.getParameter(AjaxConstants.SUBMIT_TYPE);

        if( partialParam != null && !partialParam.isEmpty() )
        {
            processPartialRequest(rootModel, request, response);
        }
        else
        {
            processCompleteRequest(rootModel, response);
        }

    }

    private void processPartialRequest(  ComponentModel model,
            HttpServletRequest request, HttpServletResponse response) throws Exception
    {
        String orginId = request.getParameter(AjaxConstants.SOURCE_ID);
        ComponentModel originComponent =
                ComponentProcessor.findComponentModel(orginId, model);
        Writer out = response.getWriter();
        if( originComponent == null )
        {
            AjaxResponseWriter.writeErrorResponse( originComponent, out );
            return;
        }
        if( isRedirect() )
        {
            AjaxResponseWriter.writeRedirectResponse( originComponent, out  );
            return;
        }

        String renders = request.getParameter(AjaxConstants.CLIENT_IDS);
        String[] rendersArr = renders.split(" ");
        AjaxResponse ajaxResponse = new AjaxResponse();

        for (int i = 0; i < rendersArr.length; i++) {
            String renderId = rendersArr[i];
            ComponentModel component = 
                    ComponentProcessor.findComponentModel(renderId, model, hsContext);
            if( component != null )
            {
//                component.setId("myRegen");
                AjaxResponseWriter.writeDeleteChange( component, this , ajaxResponse );
                AjaxResponseWriter.writeInsertChange( component, this , ajaxResponse );
            }
            System.out.println("done" + i);
        }
        
        AjaxResponseWriter.processResponse(out, ajaxResponse);
    }

    private void processCompleteRequest(
            ComponentModel model, HttpServletResponse response) throws Exception
    {
        String content = ComponentProcessor.processComponentChildrenContent(model,this);

        Map<Class, ComponentTypeStateHelper> stateHelpers =
                ComponentTagModelFactory.getStateHelperMap();

        String headers = ComponentProcessor.processComponentHeaders(stateHelpers);

        CompiledTemplate compiledStriped = TemplateCompiler.compileTemplate(content);
        String page = (String) TemplateRuntime.execute(compiledStriped, this);

        String layoutName = "/resources/portal-layout.html";
        Map var = new HashMap();
        var.put("name", "Alloy - Default Layout");

        InputStream template = getClass().getResourceAsStream( layoutName );
        Map variables = new HashMap();
        variables.put("content", page);
        variables.put("headers", headers);
        CompiledTemplate compiled3 = TemplateCompiler.compileTemplate(template);

        String src = (String) TemplateRuntime.execute(compiled3, this, variables);
        InputStream srcStream = new ByteArrayInputStream(src.getBytes());
        byte[] buffer = new byte[ 512 ];
        try
        {
            ServletOutputStream out = response.getOutputStream();
            int length = 0;
            while ( ( length = srcStream.read( buffer ) ) != -1 )
            {
                out.write( buffer, 0, length );
            }
        }
        finally
        {
            try
            {
                srcStream.close();
            }
            catch ( Exception e )
            {
                e.printStackTrace();
            }
        }
    }

    private ActionBeanContext context;

    @Override
    public void setContext(ActionBeanContext context) {
        this.context = context;
    }

    @Override
    public ActionBeanContext getContext() {
        return this.context;
    }

    public boolean isRedirect() {
        return redirect;
    }

    public void setRedirect(boolean redirect) {
        this.redirect = redirect;
    }


}
